package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.dto.CourseBaseDTO;
import com.xuecheng.api.content.model.qo.QueryCourseBaseModel;
import com.xuecheng.api.content.model.vo.CourseBaseVO;
import com.xuecheng.common.domain.code.CommonErrorCode;
import com.xuecheng.common.domain.page.PageRequestParams;
//import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.domain.page.PageVO;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseChargeEnum;
import com.xuecheng.common.util.StringUtil;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.entity.CourseBase;
import com.xuecheng.content.entity.CourseMarket;
import com.xuecheng.content.mapper.CourseBaseMapper;
import com.xuecheng.content.service.CourseBaseService;
import com.xuecheng.content.service.CourseMarketService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;

/**
 * <p>
 * 课程基本信息 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CourseBaseServiceImpl extends ServiceImpl<CourseBaseMapper, CourseBase> implements CourseBaseService {

    @Autowired
    private CourseMarketService courseMarketService;

//    @Override
//    public List<CourseBase> queryAll() {
//        List<CourseBase> list = this.list();
//        return list;
//    }

    @Override
    public PageVO queryCourseBaseList(PageRequestParams params, QueryCourseBaseModel model, Long companyId) {
//            1.判断是否需要开启事务(查询,所以不需要开启事务)
//            2.判断关键数据(分页数据,条件查询数据)
        //判断分页数据
        Long pageNo = params.getPageNo();
        Integer pageSize = params.getPageSize();
        if (ObjectUtils.isEmpty(pageNo)||pageNo<0){
            params.setPageNo(PageRequestParams.DEFAULT_PAGE_NUM);
        }
        if (ObjectUtils.isEmpty(pageSize)||pageSize<0){
            params.setPageSize(PageRequestParams.DEFAULT_PAGE_SIZE);
        }
//            3.构建mp分页对象
        Page<CourseBase> courseBasePage = new Page<>(pageNo,pageSize);
//            4.构建条件查询对象
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtil.isNotBlank(model.getCourseName())){

            queryWrapper.like(CourseBase::getName,model.getCourseName());
        }
        if (StringUtil.isNotBlank(model.getAuditStatus())){
            queryWrapper.eq(CourseBase::getAuditStatus,model.getAuditStatus());
        }
        queryWrapper.eq(CourseBase::getCompanyId,companyId);
        queryWrapper.eq(CourseBase::getStatus, CommonEnum.USING_FLAG.getCode());
//            5.查询数据
        Page<CourseBase> page = this.page(courseBasePage, queryWrapper);
        List<CourseBase> records = page.getRecords();
        long total = page.getTotal();
        //将po数据装为dto数据
        //TODO:
        List<CourseBaseDTO> dtos = Collections.EMPTY_LIST;
        if (!CollectionUtils.isEmpty(records)){
            dtos= CourseBaseConvert.INSTANCE.entitys2Dtos(records);
        }

//            6.封装数据,进行返回
        PageVO pageVO = new PageVO(dtos,total,pageNo,pageSize);
        return pageVO;
    }





    //          todo:  1.判断是否需要事务
//          todo:  2.判断关键数据(数据表字段为非空,前端的必填项,接口文档Yapi)
                        //todo:companyId name(课程名称) mt,st(课程的大分类和小分类) grade(课程的等级)
                        //todo:teachmode(课程的模式) users(适用人群) audit_status(审核的状态,后端填写的不需要判断) pic(上传图片,后续判断)
//          todo:  3.将dto转为po数据,并赋值审核状态默认值(保存,未提交)
//          todo:  4.保存数据
//          todo:    4.1 保存课程的基本信息数据
//          todo:        判断保存的结果
//          todo:    4.2 保存课程的营销数据
//          todo:        判断保存的结果
//          todo:  5.将最新数据查出来,转为DTO进行返回
    @Transactional
    public CourseBaseDTO createCourseBase(CourseBaseDTO dto) {


        verifyCourseMsg(dto);

        //          todo:  3.将dto转为po数据,并赋值审核状态默认值(保存,未提交)
        CourseBase courseBase = CourseBaseConvert.INSTANCE.dto2Entity(dto);
        courseBase.setAuditStatus(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode());
//          todo:    4.1 保存课程的基本信息数据
        boolean baseResult = this.save(courseBase);
//          todo:        判断保存的结果
        if (!baseResult){
            throw new RuntimeException("课程基本信息保存失败");
        }
//          todo:    4.2 保存课程的营销数据
        CourseMarket courseMarket = new CourseMarket();
        courseMarket.setCourseId(courseBase.getId());
        courseMarket.setCharge(dto.getCharge());
        //TODO:如果课程的收费规则是收费的
        if (CourseChargeEnum.CHARGE_YES.getCode().equals(dto.getCharge())){
            //TODO:如果课程是收费的,那么收费价格也不能为空
            if (ObjectUtils.isEmpty(dto.getPrice())){
                throw new RuntimeException("价格不能为空");
            }
        }
        //todo:courseMarket.setPrice要的是float型,dto.getPrice()是BigDecimal
        courseMarket.setPrice(dto.getPrice().floatValue());
        boolean marketResult = courseMarketService.save(courseMarket);
//          todo:        判断保存的结果
        if (!marketResult){
            throw new RuntimeException("课程营销信息保存失败");
        }

        //5,TODO:转为dto并返回
        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2Dto(courseBase);
        courseBaseDTO.setCharge(dto.getCharge());
        courseBaseDTO.setPrice(dto.getPrice());

        return courseBaseDTO;
    }

    private void verifyCourseMsg(CourseBaseDTO dto) {
        //          todo:  2.判断关键数据
        if (ObjectUtils.isEmpty(dto.getCompanyId())){
          //TODO: 拋异常:
          //TODO:      1.可以终止程序
          //TODO:      2.可以将错误信息返回
          //TODO:      3.运行时期异常,编译时期不用处理
            throw  new RuntimeException("公司id不能为空");
        }
        if (StringUtil.isBlank(dto.getName())){
            throw  new RuntimeException("课程名称不能为空");
        }
        if (StringUtil.isBlank(dto.getMt())){
            throw  new RuntimeException("课程的大分类不能为空");
        }
        if (StringUtil.isBlank(dto.getSt())){
            throw  new RuntimeException("课程的小分类不能为空");
        }
        if (StringUtil.isBlank(dto.getGrade())){
            throw  new RuntimeException("课程的等级不能为空");
        }
        if (StringUtil.isBlank(dto.getTeachmode())){
            throw  new RuntimeException("课程的教学模式不能为空");
        }
        if (StringUtil.isBlank(dto.getUsers())){
            throw  new RuntimeException("课程的使用人群不能为空");
        }
        if (StringUtil.isBlank(dto.getCharge())){
            throw  new RuntimeException("课程的收费规则不能为空");
        }
    }


    /*
* 业务分析:
* 1.是否开启事务
* 2.判断关键数据
* courseBaseId,commpanyId
* 3.判断业务数据
* 课程是否是同一家机构
* 课程是否被删除
* 4.将查询的数据转成DTO
*
* */
    public CourseBaseDTO getByCourseId(Long courseBaseId, long commpanyId) {
    if (ObjectUtils.isEmpty(courseBaseId) || ObjectUtils.isEmpty(commpanyId)){
        throw new RuntimeException(CommonErrorCode.E_403000.getDesc());
    }

        CourseBase courseBase = getCourseBaseAndLogicVerify(courseBaseId, commpanyId);

        CourseBaseDTO courseBaseDTO = CourseBaseConvert.INSTANCE.entity2Dto(courseBase);

        //TODO:基础信息查出来了,而营销信息还未查出来
        LambdaQueryWrapper<CourseMarket> marketLambdaQueryWrapper = new LambdaQueryWrapper<>();
        marketLambdaQueryWrapper.eq(CourseMarket::getCourseId,courseBaseId);
        CourseMarket courseMarket = courseMarketService.getOne(marketLambdaQueryWrapper);
        courseBaseDTO.setCharge(courseMarket.getCharge());
        //TODO:courseBaseDTO.setPrice要的是BigDecimal类型的数据
        courseBaseDTO.setPrice(new BigDecimal(courseMarket.getPrice()));

        return courseBaseDTO;
    }

    private CourseBase getCourseBaseAndLogicVerify(Long courseBaseId, long commpanyId) {
        LambdaQueryWrapper<CourseBase> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseBase::getId, courseBaseId);
        queryWrapper.eq(CourseBase::getCompanyId, commpanyId);
        CourseBase courseBase = this.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(courseBase)){
            throw new RuntimeException("课程基本信息不存在");
        }

        if (!ObjectUtils.nullSafeEquals(courseBase.getStatus(),CommonEnum.USING_FLAG.getCodeInt())){
            throw new RuntimeException("课程基本信息已删除");
        }
        return courseBase;
    }

    /*
    * yewufenxi
    * 1.事务
    * 2.判断关键数据(参考添加的判断)
    * 3.判断业务数据
    *  课程的基础信息
    *  是否属于同一家机构
    *  是否被删除
    *  课程的审核状态（未提交，审核未通过才可以修改）
    * 4.将dto数据转为po数据
    * 5.修改数据
    *   修改课程基础数据
    *   课程营销信息
    * 6.将最新数据返回给dto
    * */
   @Transactional
    public CourseBaseDTO modifyCourseBase(CourseBaseDTO courseBaseDTO) {
      //2.判断关键数据(参考添加的判断)
       verifyCourseMsg(courseBaseDTO);
       //TODO:id不能为空，修改信息
       if (ObjectUtils.isEmpty(courseBaseDTO.getCourseBaseId())){
           throw new RuntimeException("修改课程id不能为空");
       }
      //3.判断业务数据
      //        课程的基础信息
      //        是否属于同一家机构
      //        是否被删除
      //        课程的审核状态（未提交，审核未通过才可以修改）
       CourseBase courseBase = getCourseBaseAndLogicVerify(courseBaseDTO.getCourseBaseId(), courseBaseDTO.getCompanyId());
       //判断审核状态
       if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(courseBase.getAuditStatus())||
       CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(courseBase.getAuditStatus())
       ||CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(courseBase.getAuditStatus())){
           throw new RuntimeException("课程审核状态异常");
       }
       //4.将dto数据转为po数据
       CourseBase po = CourseBaseConvert.INSTANCE.dto2Entity(courseBaseDTO);
//       CourseMarket courseMarket = new CourseMarket();
//       courseMarket.setCharge(courseBaseDTO.getCharge());
//       courseMarket.setPrice(courseBaseDTO.getPrice().floatValue());
       //5.修改数据
       //        修改课程基础数据
       //TODO:修改的数据较多的情况下，推荐用updataById(要修改的实体类对象)
       boolean courseResult = this.updateById(po);
       if (!courseResult){
           throw new RuntimeException("修改课程基础信息失败");
       }
       //课程营销信息
       //TODO:修改的数据较少的情况下，推荐用Lambdaupdatewrapper
       LambdaUpdateWrapper<CourseMarket> updateWrapper = new LambdaUpdateWrapper<>();
       updateWrapper.set(CourseMarket::getCharge,courseBaseDTO.getCharge());
       updateWrapper.set(CourseMarket::getPrice,courseBaseDTO.getPrice().floatValue());
       updateWrapper.eq(CourseMarket::getCourseId,courseBaseDTO.getCourseBaseId());
       //6.将最新数据返回给dto
       boolean marketResult = courseMarketService.update(updateWrapper);
       if (!marketResult){
           throw new RuntimeException("修改课程营销信息失败");
       }

       //TODO:修改信息，查出来，再转dto返回
       CourseBase resultPo = this.getById(courseBaseDTO.getCourseBaseId());
       CourseBaseDTO resultDto = CourseBaseConvert.INSTANCE.entity2Dto(resultPo);
       resultDto.setCharge(courseBaseDTO.getCharge());
       resultDto.setPrice(courseBaseDTO.getPrice());
       return resultDto;
    }

   //TODO:业务分析：
   //TODO:    1.是否需要事务
   //TODO:    2.判断关键数据
   //TODO:        courseBaseId   companyId
   //TODO:    3.判断业务数据
   //TODO:        是否属于同一个机构，是否被删除，判断课程的是审核状态
   //TODO:    4.修改要被删除的数据（假删除，所以是修改）
    @Transactional
    public void removeCourseBase(Long courseBaseId, Long companyId) {
//TODO:    2.判断关键数据
        if (ObjectUtils.isEmpty(courseBaseId)||ObjectUtils.isEmpty(companyId)){
            throw new RuntimeException("课程id或者机构id不能为空");
        }
        //TODO:    3.判断业务数据
        //TODO:        是否属于同一个机构，是否被删除，判断课程的是审核状态
        CourseBase courseBase = this.getById(courseBaseId);
        if (ObjectUtils.nullSafeEquals(courseBase.getCompanyId(),companyId)){
            throw new RuntimeException(CommonErrorCode.E_100108.getDesc());
        }

        if (ObjectUtils.isEmpty(courseBase)){
            throw new RuntimeException(CommonErrorCode.E_100104.getDesc());
        }

        if (CourseAuditEnum.AUDIT_COMMIT_STATUS.getCode().equals(courseBase.getAuditStatus())||
                CourseAuditEnum.AUDIT_PASTED_STATUS.getCode().equals(courseBase.getAuditStatus())
                ||CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode().equals(courseBase.getAuditStatus())){
            throw new RuntimeException("课程审核状态异常");
        }

        //TODO:    4.修改要被删除的数据（假删除，所以是修改）
        LambdaUpdateWrapper<CourseBase> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(CourseBase::getStatus,CommonEnum.DELETE_FLAG);
        updateWrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        updateWrapper.eq(CourseBase::getId,courseBaseId);
        boolean updateResult = this.update(updateWrapper);
        if (!updateResult){
            throw new RuntimeException("删除课程失败");
        }

    }
}
